#pragma once
#include <memory>
#include <vector>
#include <map>
#include <utility>
#include "VarianceGammaDistribution.h"
#include "TaylorSeries.h"

class VGQSeries : public TaylorSeries
{
public:
	VGQSeries(double mu, double lambda, double alpha, double beta);
	VGQSeries(std::shared_ptr<VarianceGammaDistribution > pvgDistribution);
	virtual ~VGQSeries(void);
	
	virtual void SetInitialCondition(double u);
	virtual std::pair<double, double> GetInitialCondition() const { return make_pair(_u0, _x0); };

protected:
	
	double _u0, _x0, _N0, _zeroQuantileLocation;
	
	double _mu, _lambda, _alpha, _beta, _gamma;

	std::shared_ptr<VarianceGammaDistribution > _pvgDistribution;

	double A(unsigned int n, double y);
	double B(unsigned int n, double y);
	double C(unsigned int n, double y);

	double a(unsigned int n);
	double b(unsigned int n);
	double c(unsigned int n);
	double d(unsigned int n);
	double g(unsigned int n);
	double h(unsigned int n);
	double q(unsigned int n, unsigned int k);

	virtual double q(unsigned int n);

	void clearCache();

	std::vector<double> _va;
	std::vector<double> _vb;
	std::vector<double> _vc;
	std::vector<double> _vd;
	std::vector<double> _vg;
	std::vector<double> _vh;
	std::vector<double>& _vq;
	std::map<unsigned int, std::vector<double> > _mq; 

private:
	void initialize();

};

